﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using TM.Common.Extensions;
using TM.Data.Contracts;
using TM.Model;

namespace TM.Data.ViewModels.VmMapper
{
    public class VmMapper : IVmMapper
    {
        private DataTable projectTable;
        private DataTable taskTable;

        public IUnitOfWork UoW { get; private set; }

        public VmMapper()
            : this(new IoCParams())
        {

        }

        public VmMapper(IIoCParams ioCParams)
        {
            UoW = ioCParams.UnitOfWork;
        }

        #region Implementation of IVmMapper

        public Session ExtractFromDbo(bool brief = false, Guid? projectId = null)
        {
            if (projectId.HasValue)
            {
                var vmPr = ExtractProjectDbo(UoW.Project.GetById(projectId.Value), brief);

                if (vmPr == null) return new Session() { Projects = new List<VmProject>() };

                return new Session()
                           {
                               CurrentProjectId = 0,
                               Projects = new List<VmProject>()
                                              {
                                                  vmPr
                                              },
                               ProjectsDataSet = new DataSet("ProjectDs")
                           };
            }

            var projects = UoW.Project.GetAll();
            if (projects.Count() > 0)
            {
                Session session = new Session();
                session.Projects = new List<VmProject>();
                foreach (var project in projects)
                {
                    VmProject prj = ExtractProjectDbo(project, brief);
                    session.Projects.Add(prj);
                }

                return session;
            }

            return null;
        }

        public Session ExtractFromDboAsDataSet(bool brief = false, Guid? projectId = null)
        {
            Session session = ExtractFromDbo(brief, projectId);
            if (session != null && session.Projects.Count > 0)
            {
                projectTable = ExtractProjectTable(session.Projects);
                taskTable = ExtractTaskTable(session.Projects);

                session.ProjectsDataSet.Tables.Add(projectTable);
                session.ProjectsDataSet.Tables.Add(taskTable);
            }
            else
            {
                session.ProjectsDataSet = new DataSet("ProjectDs");
                projectTable = new DataTable("Projects");
                taskTable = new DataTable("Tasks");

                session.ProjectsDataSet.Tables.Add(projectTable);
                session.ProjectsDataSet.Tables.Add(taskTable);
            }

            return session;
        }

        private DataTable ExtractTaskTable(List<VmProject> projects)
        {
            DataTable dataTable = new DataTable("Tasks");
            dataTable.Columns.Add("ProjectId", typeof(Guid));
            dataTable.Columns.Add("ID", typeof(Guid));
            dataTable.Columns.Add("ParentID", typeof(Guid));
            dataTable.Columns.Add("Name", typeof(string));
            dataTable.Columns.Add("DescDetails", typeof(string));
            dataTable.Columns.Add("Status", typeof(Guid));
            dataTable.Columns.Add("Resources", typeof(string));
            dataTable.Columns.Add("Scopes", typeof(string));
            dataTable.Columns.Add("Evidents", typeof(string));
            dataTable.Columns.Add("Methology", typeof(string));
            dataTable.Columns.Add("StartDate", typeof(DateTime));
            dataTable.Columns.Add("EndDate", typeof(DateTime));
            dataTable.Columns.Add("Duration", typeof(TimeSpan));
            dataTable.Columns.Add("Constraint", typeof(object));
            dataTable.Columns.Add("PercentCompleted", typeof(decimal));
            dataTable.Columns.Add("ProjectKey", typeof(string));
            dataTable.Columns.Add("AllProperties", typeof(Byte[]));

            foreach (var vmProject in projects)
            {
                foreach (var task in vmProject.Tasks)
                {
                    dataTable.Rows.Add(new object[]
                                       {
                                           vmProject.ID,task.ID, task.ParentID, task.Name,task.DescDetails,
                                           task.Status == null ? null : (object)task.Status.ID,
                                           ExtractResourceString(task.Resources),
                                           ExtractScopeString(task.Scopes),
                                           ExtractEvidentString(task.Evidents),
                                           task.Methology,
                                           task.StartDate.HasValue ? (object)task.StartDate.Value:System.DBNull.Value,
                                           task.EndDate.HasValue ? (object)task.EndDate.Value:System.DBNull.Value,
                                           task.Duration,
                                           Infragistics.Win.UltraWinSchedule.TaskConstraint.StartNoEarlierThan,
                                           20,
                                           vmProject.ProjectKey
                                           
                                       });
                }
            }

            return dataTable;
        }

        private string ExtractEvidentString(List<VmEvident> evidents)
        {
            var str = "";
            foreach (var evident in evidents)
            {
                str += evident.ID + ";";
            }

            if (!string.IsNullOrEmpty(str))
            {
                str = str.TrimEnd(';');
                return str;
            }

            return null;
        }

        private string ExtractScopeString(List<VmScope> scopes)
        {
            var str = "";
            foreach (var scope in scopes)
            {
                str += scope.ID + ";";
            }

            if (!string.IsNullOrEmpty(str))
            {
                str = str.TrimEnd(';');
                return str;
            }

            return null;
        }

        private string ExtractResourceString(List<VmResource> resources)
        {
            var str = "";
            foreach (var resource in resources)
            {
                str += resource.ID + ";";
            }

            if (!string.IsNullOrEmpty(str))
            {
                str = str.TrimEnd(';');
                return str;
            }

            return null;
        }

        private DataTable ExtractProjectTable(List<VmProject> projects)
        {
            DataTable dataTable = new DataTable("Projects");
            dataTable.Columns.Add("ID", typeof(Guid));
            dataTable.Columns.Add("Name", typeof(string));
            dataTable.Columns.Add("ProjectOwner", typeof(Guid));
            dataTable.Columns.Add("StartDate", typeof(DateTime));
            dataTable.Columns.Add("ProjectKey", typeof(string));

            foreach (var vmProject in projects)
            {
                dataTable.Rows.Add(new object[]
                                       {
                                           vmProject.ID,
                                           vmProject.Name,
                                           (vmProject.ProjectOwner == null ? new Guid?() : vmProject.ProjectOwner.ID),
                                           vmProject.StartDate,
                                           vmProject.ProjectKey
                                       });
            }

            return dataTable;
        }

        public VmProject ExtractProjectDbo(Project projectDbo, bool brief)
        {
            if (projectDbo == null)
            {
                return null;
            }

            var vmProject = new VmProject()
            {
                ID = projectDbo.ID,
                Name = projectDbo.Name,
                ProjectOwner = (projectDbo.ProjectOwnerId.HasValue ? ExtractResourceDbo(projectDbo.ProjectOwnerId.Value) : null),
                StartDate = projectDbo.EstimatedStart.HasValue ? projectDbo.EstimatedStart.Value : DateTime.Now,
                ProjectKey = "Project-" + projectDbo.ID
            };

            if (brief) return vmProject;

            var projectTasks = UoW.Task.GetAllOfProject(vmProject.ID);
            vmProject.Tasks = new List<VmProjectTask>();

            foreach (var task in projectTasks)
            {
                vmProject.Tasks.Add(new VmProjectTask()
                                        {
                                            ProjectId = vmProject.ID,
                                            ProjectKey = vmProject.ProjectKey,
                                            ID = task.ID,
                                            Name = task.Name,
                                            DescDetails = task.DescDetails,
                                            StartDate = task.StartDate,
                                            EndDate = task.EndDate,
                                            Evidents = ExtractEvidentsDbo(task.Evidents),
                                            Resources = ExtractResourcesDbo(task.Resources),
                                            Scopes = ExtractScopesDbo(task.Scopes),
                                            Methology = task.Methology,
                                            ParentID = task.ParentID,
                                            Status = ExtractStatusDbo(task.StatusID),
                                        });
            }

            return vmProject;
        }
        public List<ProjectTask> ExtractTaskDboFormSessionInAppointment(Session session)
        {
            if (projectTable.Rows.Count > 0 && taskTable.Rows.Count > 0)
            {
                var projectId = Guid.Parse(projectTable.Rows[0]["ID"].ToString());

                List<ProjectTask> lst = new List<ProjectTask>();
                foreach (DataRow row in taskTable.Rows)
                {
                    ProjectTask projectTask = new ProjectTask();
                    projectTask.ProjectID = projectId;
                    projectTask.Name = (row["Name"] == null || string.IsNullOrEmpty(row["Name"].ToString()) ? string.Empty : row["Name"].ToString());
                    projectTask.ID = (row["ID"] == null || string.IsNullOrEmpty(row["ID"].ToString()) ? Guid.NewGuid() : Guid.Parse(row["ID"].ToString()));
                    projectTask.StartDate = (row["StartDate"] == null || string.IsNullOrEmpty(row["StartDate"].ToString()) ? new DateTime?() : DateTime.Parse(row["StartDate"].ToString()));
                    projectTask.EndDate = (row["EndDate"] == null || string.IsNullOrEmpty(row["EndDate"].ToString()) ? new DateTime?() : DateTime.Parse(row["EndDate"].ToString()));
                    projectTask.ParentID = (row["ParentID"] == null || string.IsNullOrEmpty(row["ParentID"].ToString()) ? new Guid?() : Guid.Parse(row["ParentID"].ToString()));
                    projectTask.DescDetails = (row["DescDetails"] == null || string.IsNullOrEmpty(row["DescDetails"].ToString()) ? string.Empty : row["DescDetails"].ToString());
                    projectTask.Resources = (row["Resources"] == null || string.IsNullOrEmpty(row["Resources"].ToString()) ? string.Empty : row["Resources"].ToString());
                    projectTask.StatusID = (row["Status"] == null || string.IsNullOrEmpty(row["Status"].ToString()) ? Guid.NewGuid() : Guid.Parse(row["Status"].ToString()));
                    projectTask.SpentTime = (row["PercentCompleted"] == null || string.IsNullOrEmpty(row["PercentCompleted"].ToString()) ? new decimal?() : decimal.Parse(row["PercentCompleted"].ToString()));
                  //  {
                      //  ProjectID = projectId,
                     //   ID = (row["ID"] == null || string.IsNullOrEmpty(row["ID"].ToString()) ? Guid.NewGuid() : Guid.Parse(row["ID"].ToString())),
                        //ParentID = (row["ParentID"] == null || string.IsNullOrEmpty(row["ParentID"].ToString()) ? new Guid?() : Guid.Parse(row["ParentID"].ToString())),
                    //    Name = (row["Name"] == null || string.IsNullOrEmpty(row["Name"].ToString()) ? string.Empty : row["Name"].ToString()),
                        //DescDetails = (row["DescDetails"] == null || string.IsNullOrEmpty(row["DescDetails"].ToString()) ? string.Empty : row["DescDetails"].ToString()),
                       // StatusID = (row["Status"] == null || string.IsNullOrEmpty(row["Status"].ToString()) ? Guid.NewGuid() : Guid.Parse(row["Status"].ToString())),
                        //Resources = (row["Resources"] == null || string.IsNullOrEmpty(row["Resources"].ToString()) ? string.Empty : row["Resources"].ToString()),
                       // Scopes = (row["Scopes"] == null || string.IsNullOrEmpty(row["Scopes"].ToString()) ? string.Empty : row["Scopes"].ToString()),
                      //  Evidents = (row["Evidents"] == null || string.IsNullOrEmpty(row["Evidents"].ToString()) ? string.Empty : row["Evidents"].ToString()),
                      //  Methology = (row["Methology"] == null || string.IsNullOrEmpty(row["Methology"].ToString()) ? string.Empty : row["Methology"].ToString()),
                    //    StartDate = (row["StartDate"] == null || string.IsNullOrEmpty(row["StartDate"].ToString()) ? new DateTime?() : DateTime.Parse(row["StartDate"].ToString())),
                   //     EndDate = DateTime.Parse(row["StartDate"].ToString()).AddMinutes(TimeSpan.Parse(row["Duration"].ToString()).TotalMinutes),
                      //  SpentTime = (row["PercentCompleted"] == null || string.IsNullOrEmpty(row["PercentCompleted"].ToString()) ? new decimal?() : decimal.Parse(row["PercentCompleted"].ToString()))

                  //  };
                    lst.Add(projectTask);
                }

                return lst;
            }


            return new List<ProjectTask>();
        }
        public List<ProjectTask> ExtractTaskDboFormSession(Session session)
        {
            //dataTable.Columns.Add("ProjectId", typeof(Guid));
            //dataTable.Columns.Add("ID", typeof(Guid));
            //dataTable.Columns.Add("ParentID", typeof(Guid));
            //dataTable.Columns.Add("Name", typeof(string));
            //dataTable.Columns.Add("DescDetails", typeof(string));
            //dataTable.Columns.Add("Status", typeof(Guid));
            //dataTable.Columns.Add("Resources", typeof(string));
            //dataTable.Columns.Add("Scopes", typeof(string));
            //dataTable.Columns.Add("Evidents", typeof(string));
            //dataTable.Columns.Add("Methology", typeof(string));
            //dataTable.Columns.Add("StartDate", typeof(DateTime));
            //dataTable.Columns.Add("EndDate", typeof(DateTime));
            //dataTable.Columns.Add("Duration", typeof(TimeSpan));
            //dataTable.Columns.Add("Constraint", typeof(object));
            //dataTable.Columns.Add("PercentCompleted", typeof(decimal));
            //dataTable.Columns.Add("ProjectKey", typeof(string));
            //dataTable.Columns.Add("AllProperties", typeof(Byte[]));
            
            if(projectTable.Rows.Count>0 && taskTable.Rows.Count>0)
            {
                var projectId = Guid.Parse(projectTable.Rows[0]["ID"].ToString());

                List<ProjectTask> lst = new List<ProjectTask>();
                foreach (DataRow row in taskTable.Rows)
                {
                    ProjectTask projectTask = new ProjectTask()
                                                  {
                                                      ProjectID = projectId,
                                                      ID = (row["ID"]==null||string.IsNullOrEmpty(row["ID"].ToString())? Guid.NewGuid():Guid.Parse(row["ID"].ToString())),
                                                      ParentID = (row["ParentID"] == null || string.IsNullOrEmpty(row["ParentID"].ToString()) ? new Guid?() : Guid.Parse(row["ParentID"].ToString())),
                                                      Name = (row["Name"] == null || string.IsNullOrEmpty(row["Name"].ToString()) ? string.Empty : row["Name"].ToString()),
                                                      DescDetails = (row["DescDetails"] == null || string.IsNullOrEmpty(row["DescDetails"].ToString()) ? string.Empty : row["DescDetails"].ToString()),
                                                      StatusID = (row["Status"] == null || string.IsNullOrEmpty(row["Status"].ToString()) ? Guid.NewGuid() : Guid.Parse(row["Status"].ToString())),
                                                      Resources = (row["Resources"] == null || string.IsNullOrEmpty(row["Resources"].ToString()) ? string.Empty : row["Resources"].ToString()),
                                                      Scopes = (row["Scopes"] == null || string.IsNullOrEmpty(row["Scopes"].ToString()) ? string.Empty : row["Scopes"].ToString()),
                                                      Evidents = (row["Evidents"] == null || string.IsNullOrEmpty(row["Evidents"].ToString()) ? string.Empty : row["Evidents"].ToString()),
                                                      Methology = (row["Methology"] == null || string.IsNullOrEmpty(row["Methology"].ToString()) ? string.Empty : row["Methology"].ToString()),
                                                      StartDate = (row["StartDate"] == null || string.IsNullOrEmpty(row["StartDate"].ToString()) ? new DateTime?() : DateTime.Parse(row["StartDate"].ToString())),
                                                      EndDate = DateTime.Parse(row["StartDate"].ToString()).AddMinutes(TimeSpan.Parse(row["Duration"].ToString()).TotalMinutes),
                                                      SpentTime = (row["PercentCompleted"] == null || string.IsNullOrEmpty(row["PercentCompleted"].ToString()) ? new decimal?() : decimal.Parse(row["PercentCompleted"].ToString()))

                                                  };
                    lst.Add(projectTask);
                }

                return lst;
            }
                
            
            return new List<ProjectTask>();
        }

        public List<VmProjectTask> ExtractVmTasksFormSession(Session session)
        {
            throw new NotImplementedException();
        }

        private VmTaskStatus ExtractStatusDbo(Guid status)
        {
            var taskStatus = UoW.Status.GetById(status);

            if (taskStatus != null)
            {
                return new VmTaskStatus() { ID = taskStatus.ID, Name = taskStatus.Name };
            }

            return null;
        }

        private List<VmScope> ExtractScopesDbo(string scope)
        {
            if (string.IsNullOrEmpty(scope)) return new List<VmScope>();
            var ids = scope.Split(';').ToGuidArray();

            var scopeOfTask = UoW.Scope.GetAllOfTask(ids.ToArray());

            List<VmScope> scopesList = new List<VmScope>();
            foreach (var res in scopeOfTask)
            {
                scopesList.Add(new VmScope()
                                    {
                                        ID = res.ID,
                                        ScopeName = res.ScopeName
                                    });
            }

            return scopesList;
        }

        private VmResource ExtractResourceDbo(Guid resourceId)
        {

            var resourceOfTask = UoW.Resource.GetById(resourceId);

            if (resourceOfTask != null)
            {
                return new VmResource()
                {
                    ID = resourceOfTask.ID,
                    Name = resourceOfTask.Name
                };
            }

            return null;
        }

        private List<VmResource> ExtractResourcesDbo(string resources)
        {
            if (string.IsNullOrEmpty(resources)) return new List<VmResource>();
            var ids = resources.Split(';').ToGuidArray();

            var resourcesOfTask = UoW.Resource.GetAllOfTask(ids.ToArray());

            List<VmResource> resourcesList = new List<VmResource>();
            foreach (var res in resourcesOfTask)
            {
                resourcesList.Add(new VmResource()
                                    {
                                        ID = res.ID,
                                        Name = res.Name
                                    });
            }

            return resourcesList;
        }

        private List<VmEvident> ExtractEvidentsDbo(string evidents)
        {
            if (string.IsNullOrEmpty(evidents)) return new List<VmEvident>();
            var ids = evidents.Split(';').ToGuidArray();
            var evidentsOfTask = UoW.Evident.GetAllOfTask(ids.ToArray());

            List<VmEvident> evidentList = new List<VmEvident>();
            foreach (var evd in evidentsOfTask)
            {
                evidentList.Add(new VmEvident()
                                    {
                                        ID = evd.ID,
                                        EvidentName = evd.EvidentName
                                    });
            }

            return evidentList;
        }

        #endregion
    }
}
